/*
 * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 

package org.maxkey.authn.support.socialsignon.service;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.entity.SocialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.*;

public class SocialSignOnProviderService{
	private static Logger _logger = LoggerFactory.getLogger(SocialSignOnProviderService.class);
	
	   private static final String DEFAULT_SELECT_STATEMENT = "select * from mxk_socials_provider where status = 1  order by sortindex";
	    
	   
	List<SocialsProvider> socialSignOnProviders = new ArrayList<SocialsProvider>();
	
	HashMap<String ,SocialsProvider>socialSignOnProviderMaps=new HashMap<String ,SocialsProvider>();
	
	private final JdbcTemplate jdbcTemplate;
	
	public SocialSignOnProviderService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate=jdbcTemplate; 
    }

	
	public SocialsProvider get(String provider){
		return socialSignOnProviderMaps.get(provider);
	}
	
	public AuthRequest  getAuthRequest(String provider,ApplicationConfig applicationConfig)  throws Exception {
		AuthRequest authRequest = null;
		AuthConfig authConfig = AuthConfig.builder()
				.clientId(this.get(provider).getClientId())
				.clientSecret(this.get(provider).getClientSecret())
				.redirectUri(applicationConfig.getServerPrefix()+ "/logon/oauth20/callback/"+provider)
				.build();
		
		if(provider.equalsIgnoreCase("WeChatOpen")) {
			authRequest = new AuthWeChatOpenRequest(authConfig);
		}else if(provider.equalsIgnoreCase("sinaweibo")) {
			authRequest = new AuthWeiboRequest(authConfig);
		}else if(provider.equalsIgnoreCase("qq")) {
			authRequest = new AuthQqRequest(authConfig);
		}else if(provider.equalsIgnoreCase("Alipay")) {
		    String alipayPublicKey = "";
			authRequest = new AuthAlipayRequest(authConfig,alipayPublicKey);
		}else if(provider.equalsIgnoreCase("Twitter")) {
			authRequest = new AuthTwitterRequest(authConfig);
		}else if(provider.equalsIgnoreCase("google")) {
			authRequest = new AuthGoogleRequest(authConfig);
		}else if(provider.equalsIgnoreCase("microsoft")) {
			authRequest = new AuthMicrosoftRequest(authConfig);
		}else if(provider.equalsIgnoreCase("Linkedin")) {
			authRequest = new AuthLinkedinRequest(authConfig);
		}else if(provider.equalsIgnoreCase("DingTalk")) {
			authRequest = new AuthDingTalkRequest(authConfig);
		}else if(provider.equalsIgnoreCase("gitee")) {
            authRequest = new AuthGiteeRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Baidu")) {
            authRequest = new AuthBaiduRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Douyin")) {
            authRequest = new AuthDouyinRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Eleme")) {
            authRequest = new AuthElemeRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Feishu")) {
            authRequest = new AuthFeishuRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Github")) {
            authRequest = new AuthGithubRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Gitlab")) {
            authRequest = new AuthGitlabRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Huawei")) {
            authRequest = new AuthHuaweiRequest(authConfig);
        }else if(provider.equalsIgnoreCase("jd")) {
            authRequest = new AuthJdRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Meituan")) {
            authRequest = new AuthMeituanRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Mi")) {
            authRequest = new AuthMiRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Oschina")) {
            authRequest = new AuthOschinaRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Taobao")) {
            authRequest = new AuthTaobaoRequest(authConfig);
        }else if(provider.equalsIgnoreCase("Toutiao")) {
            authRequest = new AuthToutiaoRequest(authConfig);
        }else if(provider.equalsIgnoreCase("WeChatQyQrcode")) {
            authRequest = new AuthWeChatEnterpriseQrcodeRequest(authConfig);
        }else if(provider.equalsIgnoreCase("workweixin")) {
            authRequest = new AuthWeChatEnterpriseWebRequest(authConfig);
        }
		
		return authRequest;
	}
	
	public String getAccountId(String provider,AuthResponse<?> authResponse)  throws Exception {
	    if(authResponse.getData() != null) {
	        AuthUser authUser = (AuthUser)authResponse.getData();
	        _logger.debug("AuthUser[{},{},{},{},{},{},{},{},{},{},{},{}]",
	                authUser.getUuid(),
	                authUser.getUsername(),
	                authUser.getNickname(),
	                authUser.getGender(),
	                authUser.getEmail(),
	                authUser.getCompany(),
	                authUser.getBlog(),
	                authUser.getLocation(),
	                authUser.getRemark(),
	                authUser.getSource(),
	                authUser.getBlog(),
	                authUser.getAvatar());
	        _logger.debug("RawUserInfo {}",authUser.getRawUserInfo());
    		if(provider.equalsIgnoreCase("WeChatOpen")) {
    			return authUser.getUuid();
    		}else if(provider.equalsIgnoreCase("sinaweibo")) {
    			return authUser.getUuid();
    		}else if(provider.equalsIgnoreCase("qq")) {
    			return authUser.getUuid();
    		}else if(provider.equalsIgnoreCase("Alipay")) {
    			return authUser.getUuid();
    		}else if(provider.equalsIgnoreCase("Twitter")) {
    			return authUser.getUuid();
    		}else if(provider.equalsIgnoreCase("google")) {
    			return authUser.getUuid();
    		}else if(provider.equalsIgnoreCase("microsoft")) {
    			return authUser.getUuid();
    		}else if(provider.equalsIgnoreCase("Linkedin")) {
    			return authUser.getUuid();
    		}else if(provider.equalsIgnoreCase("DingTalk")) {
    			return authUser.getUuid();
    		}else {
    		    return authUser.getUuid();
    		}
	    }
	    return null;
	}
	public List<SocialsProvider> getSocialSignOnProviders() {
		return socialSignOnProviders;
	}
	
	public void loadSocialsProviders() {
	    List<SocialsProvider> listSocialsProvider=jdbcTemplate.query(
	            DEFAULT_SELECT_STATEMENT,
                new SocialsProviderRowMapper());
        _logger.trace("query SocialsProvider " + listSocialsProvider);
        
        for(SocialsProvider socialsProvider : listSocialsProvider){
            socialSignOnProviderMaps.put(socialsProvider.getProvider(), socialsProvider);
            _logger.debug("Social Provider " + socialsProvider.getProvider() 
                                             + "(" + socialsProvider.getProviderName()+")");
            if(!socialsProvider.getHidden().equals("true")) {
                this.socialSignOnProviders.add(socialsProvider);
            }
        }
    
    _logger.debug("social SignOn Providers {}" , this.socialSignOnProviders);
	}
	
	
	private final class SocialsProviderRowMapper  implements RowMapper<SocialsProvider> {
        @Override
        public SocialsProvider mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            SocialsProvider socialsProvider=new SocialsProvider();
            socialsProvider.setId(rs.getString("id"));
            socialsProvider.setProvider(rs.getString("provider"));
            socialsProvider.setProviderName(rs.getString("providername"));
            socialsProvider.setIcon(rs.getString("icon"));
            socialsProvider.setClientId(rs.getString("clientid"));
            socialsProvider.setClientSecret(rs.getString("clientsecret"));
            socialsProvider.setAgentId(rs.getString("agentId"));
            socialsProvider.setHidden(rs.getString("hidden"));
            socialsProvider.setSortIndex(rs.getInt("sortindex"));
            socialsProvider.setStatus(rs.getInt("status"));
            return socialsProvider;
        }
    }
}
